package com.smart.tool.core;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;

/**
 * @Author gao.gwq
 * @Version DateUtils.java, v 0.1 2024年06月06日 17:22 gao.gwq
 * @Description: TODO
 */
public class DateTool {

    private final static int ONE = 1;

    private final static int TWO = 2;

    private final static int TWELVE = 12;

    /**
     * 年月日(中文) yyyy年MM月dd日
     */
    public final static String DTSIMPLECHINESE = "yyyy年MM月dd日";

    /**
     * 年月日(无下划线) yyyyMMdd
     */
    public final static String DTMONTH = "yyyyMM";

    /**
     * 年月日时分(无下划线) yyyyMMddHHmm
     */
    public final static String DTMIDDLE = "yyyyMMddHHmm";

    /**
     * 年月日时分秒(无下划线) yyyyMMddHHmmss
     */
    public final static String DTLONG = "yyyyMMddHHmmss";

    /**
     * 时分秒 HHmmss
     */
    public final static String HMSFORMAT = "HHmmss";

    /**
     * 年月日(中文) yyyy年MM月dd日 HH:mm:ss
     */
    public final static String DTSIMPLECHINESEWITHTIMESECOND = "yyyy年MM月dd日 HH:mm:ss";

    /**
     * 年月日   ， yyyy.MM.dd
     */
    public final static String DTSIMPLEBY = "yyyy.MM.dd";

    /**
     * 月日  ，MMdd
     */
    public final static String MONTHDAY = "MMdd";

    /**
     * 日 时分秒，dd HH:mm:ss
     **/
    public final static String DAY_TIME = "dd HH:mm:ss";

    public final static String TIME_YYYMMDD = "yyyyMMdd";

    public final static String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 完整时间 yyyy-MM-dd HH:mm:ss,SSS
     */
    public final static String DATE_TIME_FORMATS = "yyyy-MM-dd HH:mm:ss,SSS";

    /**
     * 完整时间 yyyy-MM-dd HH:mm:ss.SSS
     */
    public final static String DATE_TIME_FORMATS_POINT = "yyyy-MM-dd HH:mm:ss.SSS";

    public final static String DS_SIMPLE = "yyyyMMdd HH:mm:ss";
    public final static String DATE_MIN_FORMAT = "yyyy-MM-dd HH:mm";

    public final static String DATE_FORMAT = "yyyy-MM-dd";

    public final static String MONTH_FORMAT = "yyyy-MM";

    public final static String DATE_FORMAT_NUMBER = "yyyyMMdd";

    public final static String TIME_FORMAT = "HH:mm:ss";

    public final static String DIFF_DAY = "dd";

    public final static String DIFF_HOUR = "hh";

    public final static String DIFF_MINUTE = "mi";

    public final static String DIFF_SECOND = "ss";

    public final static String DIFF_MILLISECOND = "ms";

    public static final int INDEX_YEAR = 0;
    public static final int INDEX_MONTH = 1;
    public static final int INDEX_DAY = 2;
    public static final int INDEX_HOUR = 3;
    public static final int INDEX_MINUTE = 4;
    public static final int INDEX_SECOND = 5;
    public static final int INDEX_MILLISECOND = 6;

    public static final String SHANGHAI_TIME_ZONE = "Asia/Shanghai";

    /**
     * 获取当前系统时间
     *
     * @return Date
     */
    public static Date getCurrDate() {
        return new Date();
    }

    /**
     * 按照 yyyy-MM-dd HH:mm:ss 返回当前时间
     */
    public static String getCurrDateFormat() {
        return DateTool.format(getCurrDate(), DateTool.DATE_TIME_FORMAT);
    }


    /**
     * 将日期集合转换成指定 format 格式
     *
     * @param dates
     * @param format
     * @return
     */
    public static List<String> formatDates(List<Date> dates, String format) {
        List<String> datesFormat = Lists.newArrayList();
        dates.forEach(date -> {
            String dateStr = DateTool.format(date, format);
            datesFormat.add(dateStr);
        });
        return datesFormat;
    }

    /**
     * 毫秒的时间按类型转换
     *
     * @param format
     * @param milliSeconds
     * @return
     */
    public static String convertMilliSecondsFormat(String format, long milliSeconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(milliSeconds);

        SimpleDateFormat f = new SimpleDateFormat(format);
        f.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return f.format(calendar.getTime());
    }

    /**
     * 获取当前日期，精确到天
     *
     * @return
     */
    public static Date getCurrDay() {
        Date now = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(now);
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        // 将时分秒,毫秒域清零
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取当前年
     *
     * @return [2018]
     */
    public static int getCurrentYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return cal.get(Calendar.YEAR);
    }

    /**
     * 获取当前时间的月份
     *
     * @return mm [1-12]
     */
    public static int getCurrentMonth() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取当前时间的月份
     *
     * @return mm [1-12]
     */
    public static int getCurrentMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取当前天数
     *
     * @return DD[1-31]
     */
    public static int getCurrentDay() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取上一个月1号0点0分0秒的时间
     */
    public static Date getLastMonthStartTime() {
        Long currentTime = System.currentTimeMillis();

        String timeZone = "GMT+8:00";
        Calendar calendar = Calendar.getInstance();// 获取当前日期
        calendar.setTimeZone(TimeZone.getTimeZone(timeZone));
        calendar.setTimeInMillis(currentTime);
        calendar.add(Calendar.YEAR, 0);
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    /**
     * 获取指定时间格式的年，月，日，时，分，秒，毫秒
     *
     * @param date
     * @return <li>
     * <ul>day 整数数组</ul>
     * <ul>day[0]   年</ul>
     * <ul>day[1]   月</ul>
     * <ul>day[2]   日</ul>
     * <ul>day[3]   时</ul>
     * <ul>day[4]   分</ul>
     * <ul>day[5]   秒</ul>
     * <ul>day[6]   毫秒</ul>
     * </li>
     * @throws ParseException
     */
    public static int[] getDateMeta(Date date) {
        int[] day = new int[7];

        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        cal.setTime(date);
        day[INDEX_YEAR] = cal.get(Calendar.YEAR);
        day[INDEX_MONTH] = cal.get(Calendar.MONTH) + 1;
        day[INDEX_DAY] = cal.get(Calendar.DAY_OF_MONTH);
        day[INDEX_HOUR] = cal.get(Calendar.HOUR_OF_DAY);
        day[INDEX_MINUTE] = cal.get(Calendar.MINUTE);
        day[INDEX_SECOND] = cal.get(Calendar.SECOND);
        day[INDEX_MILLISECOND] = cal.get(Calendar.MILLISECOND);
        return day;
    }

    /**
     * 获取当前天数
     *
     * @return DD[1-31]
     */
    public static int getWeekOfCurrentDay() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return cal.get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 获取当前年-月
     *
     * @return
     */
    public static String getCurrentYearMonth() {
        return format(new Date(), MONTH_FORMAT);
    }

    /**
     * 2023-10-23 00:00:00
     * 时间格式化
     *
     * @param date
     * @param formatPattern
     * @return java.lang.String
     */
    public static String format(Date date, String formatPattern) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat f = new SimpleDateFormat(formatPattern);
        f.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return f.format(date);
    }

    /**
     * 文本转换成时间
     *
     * @param text
     * @param formatPattern
     * @return java.util.Date
     */
    public static Date parseDateStr(String text, String formatPattern) throws ParseException {
        if (StringUtils.isBlank(text)) {
            return null;
        }

        SimpleDateFormat f = new SimpleDateFormat(formatPattern);
        f.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        return f.parse(text);

    }

    /**
     * 检查时间格式是否合法
     *
     * @param dateStr
     * @param dateFormat
     * example:
     * 2023-10-23 00:00:00 yyyy-MM-dd HH:mm:ss  true
     * 2023-10-23 00:00:00 yyyy-MM-dd false
     * 2023-10-23 00:00:00 yyyy-MM false
     *
     */
    public static boolean checkDateFormat(String dateStr, String dateFormat) {
        if (dateStr == null
            || dateFormat == null
            || dateFormat.length() <= 0) {

            return false;
        }

        SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
        formatter.setLenient(false);

        try {
            formatter.parse(dateStr);
        } catch(ParseException e) {
            return false;
        }

        if (dateFormat.length() != dateStr.length()) {
            return false;
        }

        return true;
    }

    /**
     * 得到某月的第一秒， 例如：当前时间year=2015,month=1, 返回结果：2015-01-01 00:00:00
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getFirstSecondOfMonth(Integer year, Integer month) {
        // 读取配置表中配置
        Calendar nowDate = Calendar.getInstance();
        nowDate.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        nowDate.set(Calendar.YEAR, year);
        nowDate.set(Calendar.MONTH, month - 1);
        nowDate.set(Calendar.DATE, 1);
        nowDate.set(Calendar.HOUR_OF_DAY, 0);
        nowDate.set(Calendar.MINUTE, 0);
        nowDate.set(Calendar.SECOND, 0);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }

    /**
     * 获取当前月的第一天，第一秒
     *
     * @param date
     * @return
     */
    public static Date getFirstSecOfMonth(Date date) {
        // 读取配置表中配置
        Calendar nowDate = Calendar.getInstance();
        nowDate.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        nowDate.setTime(date);
        nowDate.set(Calendar.YEAR, nowDate.get(Calendar.YEAR));
        nowDate.set(Calendar.MONTH, nowDate.get(Calendar.MONTH));
        nowDate.set(Calendar.DATE, 1);
        nowDate.set(Calendar.HOUR_OF_DAY, 0);
        nowDate.set(Calendar.MINUTE, 0);
        nowDate.set(Calendar.SECOND, 0);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }

    /**
     * 得到某月的最后一秒， 例如：当前时间year=2015,month=1, 返回结果：2015-01-31 23:59:59
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastSecondOfMonth(Integer year, Integer month) {
        // 读取配置表中配置
        Calendar nowDate = Calendar.getInstance();
        nowDate.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        nowDate.set(Calendar.YEAR, year);
        nowDate.set(Calendar.MONTH, month - 1);
        nowDate.set(Calendar.DATE, 1);
        nowDate.roll(Calendar.DATE, -1);
        nowDate.set(Calendar.HOUR_OF_DAY, 23);
        nowDate.set(Calendar.MINUTE, 59);
        nowDate.set(Calendar.SECOND, 59);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }

    /**
     * 得到下个月的月最后一天，最后一秒 例如：当前时间2015-08-18 10:30:00,monthMonth=1, 返回结果：2015-09-30 23:59:59
     *
     * @param monthAfter
     * @return
     */
    public static Date getLastSecondOfNextMonth(Date date, Integer monthAfter) {
        Calendar nowDate = Calendar.getInstance();
        nowDate.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        nowDate.setTime(date);

        nowDate.add(Calendar.MONTH, monthAfter);
        nowDate.set(Calendar.DATE, 1);
        nowDate.roll(Calendar.DATE, -1);
        nowDate.set(Calendar.HOUR_OF_DAY, 23);
        nowDate.set(Calendar.MINUTE, 59);
        nowDate.set(Calendar.SECOND, 59);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }


    /**
     * 判断指定时间是否在范围内, fromTime <= targetTime < toTime
     *
     * @param targetTime
     * @param fromTime   起始时间, 闭区间
     * @param toTime     结束时间, 开区间
     * @return
     */
    public static boolean checkTimeInRange(Date targetTime, Date fromTime, Date toTime) {
        return targetTime.compareTo(fromTime) >= 0 && targetTime.compareTo(toTime) < 0;
    }

    /**
     * 获得指定年月日的最后一秒
     *
     * @param year
     * @param month
     * @param day
     * @return
     */
    public static Date getLastSecOfTargetDate(Integer year, Integer month, Integer day) {
        // 检查 month
        if (month < ONE || month > TWELVE) {
            throw new IllegalArgumentException("month不合法");
        }

        // year-month 月份至多有几天
        Integer numberOfDaysInMonth = getDayNumsOfMonth(year, month);
        // 检查 day
        if (day < ONE || day > numberOfDaysInMonth) {
            throw new IllegalArgumentException("day不合法");
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取【某天】第一毫秒
     *
     * @return
     */
    public static Date getFirstMillSecondOfDay(Date day) {
        Calendar dayCalendar = Calendar.getInstance();
        dayCalendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        dayCalendar.setTime(day);
        dayCalendar.set(Calendar.HOUR_OF_DAY, 0);
        dayCalendar.set(Calendar.MINUTE, 0);
        dayCalendar.set(Calendar.SECOND, 0);
        dayCalendar.set(Calendar.MILLISECOND, 0);
        return dayCalendar.getTime();
    }

    /**
     * 获取【某天】最后一毫秒
     *
     * @return
     */
    public static Date getLastMillSecondOfDay(Date day) {
        Calendar dayCalendar = Calendar.getInstance();
        dayCalendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        dayCalendar.setTime(day);
        dayCalendar.set(Calendar.HOUR_OF_DAY, 23);
        dayCalendar.set(Calendar.MINUTE, 59);
        dayCalendar.set(Calendar.SECOND, 59);
        dayCalendar.set(Calendar.MILLISECOND, 999);
        return dayCalendar.getTime();
    }

    /**
     * 得到【某天】的最后一秒时间
     *
     * @param date
     * @return
     */
    public static Date getLastSecondOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取【某月】最后一秒
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getLastSecondOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取当月最后一毫秒
     *
     * @return
     */
    public static Date getLastMillSecondOfMonth(Date day) {
        Calendar dayCalendar = Calendar.getInstance();
        dayCalendar.setTime(day);
        dayCalendar.add(Calendar.MONTH, 1);
        dayCalendar.set(Calendar.DAY_OF_MONTH, 1);
        dayCalendar.add(Calendar.DAY_OF_MONTH, -1);
        dayCalendar.set(Calendar.HOUR_OF_DAY, 23);
        dayCalendar.set(Calendar.MINUTE, 59);
        dayCalendar.set(Calendar.SECOND, 59);
        dayCalendar.set(Calendar.MILLISECOND, 999);
        return dayCalendar.getTime();
    }

    /**
     * 获取上月时间的年月字符串格式，如2011-03 查询历史标王信息时使用
     *
     * @return
     */
    public static String getLastYearMonth() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        sdf.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        Calendar nowDate = Calendar.getInstance();
        nowDate.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        nowDate.add(Calendar.MONTH, -1);
        return sdf.format(nowDate.getTime());
    }

    /**
     * 返回指定年月的天数
     * 比如 2023-06 一共30天, 返回 30
     *
     * @param year  指定年
     * @param month 指定月
     * @return
     */
    public static Integer getDayNumsOfMonth(Integer year, Integer month) {
        YearMonth yearMonthObject = YearMonth.of(year, month);
        Integer daysInMonth = yearMonthObject.lengthOfMonth();
        return daysInMonth;
    }



    /**
     * 计算2个日期(取整)相差的天数
     * 返回值：相差天数的绝对值
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int getDateDistance(Date startDate, Date endDate) {
        Date[] dates = {startDate, endDate};
        Calendar[] calendars = new Calendar[dates.length];
        for (int i = 0; i < dates.length; i++) {
            calendars[i] = Calendar.getInstance();
            calendars[i].setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
            calendars[i].setTime(dates[i]);
            // 小时取0
            calendars[i].set(Calendar.HOUR_OF_DAY, 0);
            // 分取0
            calendars[i].set(Calendar.MINUTE, 0);
            // 秒取0
            calendars[i].set(Calendar.SECOND, 0);
            // 毫秒取0
            calendars[i].set(Calendar.MILLISECOND, 0);
        }
        return Math.abs((int)((calendars[0].getTime().getTime() - calendars[1].getTime().getTime()) / 1000 / 60 / 60 / 24));
    }

    /**
     * 获取两个时间戳之间的差值 毫秒维度
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static long getDatetimeDistance(Date startDate, Date endDate) {
        return Math.abs(startDate.getTime() - endDate.getTime());
    }

    /**
     * 返回指定间隔时间的日期
     *
     * @param year  间隔的年数， 负数时往前推
     * @param month 间隔月数，负数往前推
     * @param day   间隔天数，负数往前推
     * @return
     */
    public static Date getAfterDate(int year, int month, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        cal.add(Calendar.YEAR, year);
        cal.add(Calendar.MONTH, month);
        cal.add(Calendar.DAY_OF_YEAR, day);
        return cal.getTime();
    }

    /**
     * 判断两个日期是否在同一天
     *
     * @param day1 不为空
     * @param day2 不为空
     * example:
     *    2024-01-01 2024-01-01 12:00:00 是同一天
     *
     */
    public static boolean isSameDay(Date day1, Date day2) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        String day1Str = sdf.format(day1);
        String day2Str = sdf.format(day2);
        return day1Str.equals(day2Str);

    }

    /**
     * 计算2个日期(取整)相差的天数、小时数、分钟数、秒数(返回值非负)
     *
     * @param startTime
     * @param endTime
     * @param format
     * @param diffKey
     * @return
     */
    public static long dateDiff(String startTime, String endTime, String format, String diffKey) throws ParseException {
        //按照传入的格式生成一个simpledateformate对象
        SimpleDateFormat sd = new SimpleDateFormat(format);
        sd.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
        long nh = 1000 * 60 * 60;// 一小时的毫秒数
        long nm = 1000 * 60;// 一分钟的毫秒数
        long ns = 1000;// 一秒钟的毫秒数
        long diff = 0;
        long day = 0;
        long hour = 0;
        long min = 0;
        long sec = 0;
            //获得两个时间的毫秒时间差异
            diff = Math.abs(sd.parse(endTime).getTime() - sd.parse(startTime).getTime());
            day = diff / nd;// 计算差多少天
            hour = diff % nd / nh + day * 24;// 计算差多少小时
            min = diff % nd % nh / nm + hour * 60;// 计算差多少分钟
            sec = diff % nd % nh % nm / ns + min * 60;// 计算差多少秒
            String DayStr = "dd";
            if (DayStr.equalsIgnoreCase(diffKey)) {
                return day;
            }
            String hourStr = "hh";
            if (hourStr.equalsIgnoreCase(diffKey)) {
                return hour;
            }
            String minStr = "mi";
            if (minStr.equalsIgnoreCase(diffKey)) {
                return min;
            }
            String secondStr = "ss";
            if (secondStr.equalsIgnoreCase(diffKey)) {
                return sec;
            }
            String msStr = "ms";
            if (msStr.equalsIgnoreCase(diffKey)) {
                return diff;
            }


        return diff;
    }


    /**
     * 把日期型转换成字符串形式。
     *
     * @param date       日期
     * @param dateFormat 日期格式，例如"yyyy/MM/dd"、"yyyy年MM月dd"
     * @return 日期字符串
     */
    public static String toLocaleString(Date date, String dateFormat) {
        if (date == null) {
            return "";
        }

        if (StringUtils.isEmpty(dateFormat)) {
            return new SimpleDateFormat(DATE_TIME_FORMAT).format(date);
        }

        return new SimpleDateFormat(dateFormat).format(date);
    }

    /**
     * 增加分钟
     * @param date
     * @param minute
     * @return
     */
    public static Date addMinute(Date date, int minute) {

        Calendar calendar = new GregorianCalendar();
        calendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        calendar.setTime(date);
        // 把当前时间往前或往后挪到指定分钟数
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }

    /**
     * 增加小时
     * 如果是负数 就是减少
     * @param date
     * @param hours
     * @return
     */
    public static Date addHours(Date date, int hours) {
        return addMinute(date, hours * 60);
    }

    /**
     * 增加秒 如果是负数 就是减少
     * @param date
     * @param secs
     * @return
     */
    public static Date addSeconds(Date date, int secs) {
        return new Date(date.getTime() + secs * 1000);
    }

    /**
     * iday = 0, 返回 date
     * idya = -1, 返回 date 前一天
     *
     * 比如：date = 2023-01-12 13:34 iday = -1
     * 返回：2023-01-11 13：34
     *
     * @param date
     * @param iday
     * @return
     */
    public static Date addDay(Date date, int iday) {

        Calendar calendar = new GregorianCalendar();
        calendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        calendar.setTime(date);
        // 把日期往后增加一天.整数往后推,负数往前移动
        calendar.add(Calendar.DATE, iday);
        return date = calendar.getTime();
    }





    /**
     * 增加月份
     * @param day
     * @param month
     * @return
     */
    public static Date addMonth(Date day, int month) {

        Calendar calendar = new GregorianCalendar();
        calendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        calendar.setTime(day);
        calendar.add(Calendar.MONTH, month);
        day = calendar.getTime();
        return day;

    }

    /**
     * 返回当天的前一天的最后一秒。 当天为：2018-10-30 15:12:13 则返回：2018-10-29 23:59:59
     *
     * @return
     */
    public static Date getLastSecondOfPreDay() {
        Calendar nowDate = Calendar.getInstance();
        nowDate.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        nowDate.add(Calendar.DAY_OF_MONTH, -1);
        nowDate.set(Calendar.HOUR_OF_DAY, 23);
        nowDate.set(Calendar.MINUTE, 59);
        nowDate.set(Calendar.SECOND, 59);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }





    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }


    public static Date buildDate(Date date, int hour, int minute, int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone(SHANGHAI_TIME_ZONE));
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, seconds);
        calendar.set(Calendar.MILLISECOND, 0);
        Date zero = calendar.getTime();
        return zero;
    }

    /**
     * 判断日期是不是今天
     *
     * @param date
     * @return 是返回true，不是返回false
     */
    public static boolean isToday(Date date) {
        if (Objects.isNull(date)) {
            return false;
        }

        // 当前时间
        Date now = new Date();
        SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMAT);
        //获取今天的日期
        String nowDay = sf.format(now);
        //对比的时间
        String day = sf.format(date);

        return day.equals(nowDay);
    }




    /**
     * 返回下一个月的开始时间  00:00:00
     *
     * @return
     */
    public static Date getNextMonthBeginTime() {
        return getNextMonthBeginTime(new Date());
    }

    /**
     * 获取指定日期下个月的开始时间
     * @param date
     * @return
     */
    public static Date getNextMonthBeginTime(Date date) {
        return DateTool.addMonth(DateTool.getFirstSecOfMonth(date), 1);
    }


    /**
     * 将时间的毫秒设置为 0
     *
     * @param date
     * @return
     */
    public static Date setMilliSecondToZero(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone(DateTool.SHANGHAI_TIME_ZONE));
        calendar.setTime(date);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }




    /**
     * 小时向下取整
     * 例：2023.6.25.15:39按小时向下取整后返回2023.6.25.15:00
     *
     * @param date
     * @return
     */
    /*public static Date roundDownHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        // 将小时数设置为当前小时的整数
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        // 将分钟数设置为0
        calendar.set(Calendar.MINUTE, 0);
        // 将秒数设置为0
        calendar.set(Calendar.SECOND, 0);
        // 将毫秒数设置为0
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }*/

    /**
     * 小时向上取整
     * 例：2023.6.25.15:39按小时向下取整后返回2023.6.25.16:00
     *
     * @param date
     * @return
     */
    /*public static Date roundUpHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        if (hour < 23) {
            // 如果当前小时数不为23，将小时数加1
            calendar.set(Calendar.HOUR_OF_DAY, hour + 1);
        } else {    // 如果当前小时数为23，将小时数设置为0，同时将日期加1天
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        }
        // 将分钟数设置为0
        calendar.set(Calendar.MINUTE, 0);
        // 将秒数设置为0
        calendar.set(Calendar.SECOND, 0);
        // 将毫秒数设置为0
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }*/





    /**
     * 返回日期相差小时数，向下取整数
     *
     * @param dateStart 一般前者小于后者dateEnd
     * @param dateEnd   截止时间
     * @return 两者相差小时数
     */
    public static int getDistanceHours(Date dateStart, Date dateEnd) {
        if (null == dateStart || null == dateEnd) {
            return -1;
        }

        return (int)((dateEnd.getTime() - dateStart.getTime()) / (1000 * 60 * 60));
    }

    /**
     * 返回日期相差分钟数，向下取整数
     *
     * @param dateStart 一般前者小于后者dateEnd
     * @param dateEnd   截止时间
     * @return 两者相差分钟数
     */
    public static int getDistanceByMinutes(Date dateStart, Date dateEnd) {
        if (null == dateStart || null == dateEnd) {
            return -1;
        }

        return (int)((dateEnd.getTime() - dateStart.getTime()) / (1000 * 60));
    }

    /**
     * 返回日期相差分钟数，向下取整数
     *
     * @param dateStart 一般前者小于后者dateEnd
     * @param dateEnd   截止时间
     * @return 两者相差分钟数
    public static BigDecimal countMinutes(Date dateStart, Date dateEnd, int scale) {
        if (null == dateStart || null == dateEnd) {
            return new BigDecimal(-1);
        }
        long diff = dateEnd.getTime() - dateStart.getTime();
        BigDecimal bigDecimalDiff = new BigDecimal(diff);
        BigDecimal divisor = new BigDecimal(1000 * 60);
        return bigDecimalDiff.divide(divisor, scale, BigDecimal.ROUND_HALF_UP);
    }*/




    /**
     * 据出生日期计算年龄（"yyyy-MM-dd"）.
     *
     * @param strBirthDay 字符串格式的出生日期.
     * @return 年龄.
     * @throws Exception 系统异常.
     */
   /* public static int getAgeByBirthday(final String strBirthDay) throws Exception {
        return getAgeByBirthday(strBirthDay, DATE_FORMAT);
    }*/

    /**
     * 根据出生日期计算年龄.
     *
     * @param strBirthDay 字符串型日期.
     * @param format      日期格式.
     * @return 未来日期返回0.
     * @throws Exception 系统异常.
     */
    /*public static int getAgeByBirthday(final String strBirthDay, final String format) throws Exception {
        DateFormat dateFormat = new SimpleDateFormat(format);
        Date birthDay = dateFormat.parse(strBirthDay);
        return getAgeByBirthday(birthDay);
    }*/

    /**
     *
     * 根据出生的年月日，获取对应的年龄
     *
     * @param birthDay 出生日期.
     * @return 年龄（未来日期返回0）.
     * @throws Exception 系统异常.
     */
    public static int getAgeByBirthday(final Date birthDay) {

        Calendar cal = Calendar.getInstance();

        if (cal.before(birthDay)) {
            return 0;
        }

        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH);
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birthDay);

        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

        int age = yearNow - yearBirth;

        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;
                }
            } else {
                age--;
            }
        }

        return age;
    }


    /**
     * 时间转换long类型
     *
     * @param date
     * @return
     */
    public static Long convertMillDate2Second(Date date) {
        return date.toInstant().getEpochSecond();
    }

    /**
     * 比较两个时间大小
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static boolean before(Date startDate, Date endDate) {
        return convertMillDate2Second(startDate) < convertMillDate2Second(endDate);
    }

    /**
     * 日期比较
     * 0 相等
     * 1 大于
     * -1 小于
     * @param startDate
     * @param endDate
     * @return
     */
    public static int compareTo(Date startDate, Date endDate) {
        long startTime = convertMillDate2Second(startDate);
        long endTime = convertMillDate2Second(endDate);
        return (Long.compare(startTime, endTime));
    }

    /**
     * 转化毫秒为Date
     *
     * @param millSecondTime 毫秒
     * @return
     */
    public static Date convertMillSecond2Date(Long millSecondTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millSecondTime);
        return calendar.getTime();
    }

    /**
     * 获取范围内的日期信息列表
     *
     * @param startDay
     * @param endDay
     * @return
     */
    public static List<Date> getDayList(Date startDay, Date endDay) {
        List<Date> workDayList = new ArrayList<>();
        Date now = new Date(startDay.getTime());
        while (!now.after(endDay)) {
            workDayList.add(now);
            now = addDay(now, 1);
        }

        return workDayList;
    }
}
